if (!window.ymacs){

    /*
     * Helper functions
     */

    function injectCSSFile( document, url )
    {
        var head = document.getElementsByTagName('head')[0];         
        var linkNode = document.createElement('link');
        linkNode.rel  = 'stylesheet';
        linkNode.type = 'text/css';
        linkNode.href = url;
        head.appendChild(linkNode);
    }

    function injectJavaScriptFile( document, url, callback )
    {
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.src = url;

        /* Attach handlers for all browsers */
        var done = false;
        script.onload = script.onreadystatechange = function()
        {
                if( !done && ( !this.readyState 
                               || this.readyState == 'loaded' 
                               || this.readyState == 'complete') )
                {
                        done = true;

                        /* Call a callback */
                        if (callback)
                            callback();

                        /* Handle memory leak in IE */
                        script.onload = script.onreadystatechange = null;
                        head.removeChild( script );
                }
        };

        head.appendChild(script);
    }

    function print(obj) {
        var a = [], i;
        for (i in obj) {
            var val = obj[i];
            if (val instanceof Function)
                val = val.toString();
            else
                val = DlJSON.encode(val);
            a.push(DlJSON.encode(i) + " : " + val);
        }
        return a.map(function(line){
            return line.replace(/^/mg, function(s) {
                return "        ";
            });
        }).join("\n");
    }


    /*
     * Event handlers
     */

    function blurYmacs(event)
    {
        if (!dummyDialog.focusInside() && !event.target.className.match('Ymacs'))
        {
            /* focusing dummyDialog makes Ymacs loose focus */
            dummyDialog.focus();
        } 
        else if (event.target.className.match('Ymacs'))
        {
            /* focusing original Gmail textarea enables 'Save draft' button */
            textarea.focus();
        }
    }


    /*
     * Ymacs injection code
     */

    /* load CSS required by Ymacs */
    injectCSSFile(document, 'http://www.ymacs.org/dl/css/default.css');
    injectCSSFile(document, 'http://www.ymacs.org/ymacs/css/ymacs.css');

    /* load DynarchLIB library, Ymacs code and run Ymacs */
    injectJavaScriptFile(document, 'http://www.ymacs.org/dl/js/thelib.js', function(){
        injectJavaScriptFile(document, 'http://www.ymacs.org/ymacs/js-minified/ymacs-min.js', runYmacs);
    });
} else {
    runYmacs();
}

/*
 * Ymacs instantiation
 */

function runYmacs() {

    var helpText = 
"# Ymacs help\n\
\n\
Ymacs is an Emacs-like editor that works in your browser.\n\
\n\
\n\
## Keybindings\n\
\n\
Existing keybindings:\n\
"+
print(Ymacs_Keymap_Emacs().constructor.KEYS)
+"\n\
\n\
## Credits\n\
\n\
Ymacs website: http://www.ymacs.org/\n\
Ymacs was created by Mihai Bazon <mihai.bazon@gmail.com>\n\
Ymacs for Gmail bookmarklet was created by Andrey Popelo <andrey@popelo.com>\n\
";

    try {
        if (!window.layout) {
            // Dummy dialog (always hidden).
            // A helper object which is used to make Ymacs loose focus.
            var dummyDialog = window.dummyDialog = new DlDialog({});
            dummyDialog.setPos(-3000, 500); //hide

            /* add onclick handler for iframe which will contain Ymacs */
            window.onclick = blurYmacs;

        // if Ymacs already exists - destroy it
        } else {
            window.layout.destroy();
        }


        // Ymacs buffers
        var letter = window.letter = new Ymacs_Buffer({ name: "letter" });
        letter.setCode(textarea.value);
        letter.setq("indent_level", 4);
        var help = window.help = new Ymacs_Buffer({ name: "*help*" });
        help.setCode(helpText);
        help.setq("indent_level", 4);

        // Ymacs
        var ymacs = window.ymacs = new Ymacs({ buffers: [ letter, help ] });
        ymacs.setColorTheme([ "light", "standard" ]);

        // Add onLineChange handler for "letter" buffer
        // Update original Gmail textarea value if anything changed in Ymacs
        letter.addEventListener("finishedEvent", function() {
            textarea.value = letter.getCode();
            textarea.focus();
        });

        // Inject Ymacs into "ymacs_container"
        var layout = window.layout = new DlLayout({});
        var element = window.element = layout.getElement();
        var container = window.container = document.getElementById("ymacs_container");
        container.innerHTML = "";
        container.appendChild(element);
        layout.packWidget(ymacs, { pos: "top", fill: "*" });
        layout.setSize({ y: 300 });

        // Execute user config file, if exists.
        try {
            ymacs.getActiveBuffer().cmd("eval_file", ".ymacs");
        } catch(ex) {}

    } catch(ex) {
            console.log(ex);
    }

    DynarchDomUtils.trash($("ymacs_loading"));
}
